package com.lysj.admin.master;

import cn.hutool.cache.Cache;
import cn.hutool.cache.CacheUtil;
import com.lysj.admin.master.auth.domain.Permission;
import com.lysj.admin.master.auth.domain.RolePermission;
import com.lysj.admin.master.auth.service.PermissionService;
import com.lysj.admin.master.auth.service.RolePermissionService;
import com.lysj.admin.master.auth.vo.PermissionCacheVO;
import com.lysj.admin.master.common.CommonConstant;
import com.lysj.admin.master.common.authentication.AuthenticationInterface;
import com.lysj.admin.master.common.enumeration.EnumInterface;
import com.lysj.admin.master.common.spring.SpringContextUtil;
import com.lysj.admin.master.common.web.ParamUtil;
import org.reflections.Reflections;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

/**
 * @author Created by zk on 2019-12-25 12:48
 * @description
 */
@Component
public class CacheManager implements ApplicationRunner {

    @Resource
    private PermissionService permissionService;
    @Resource
    private RolePermissionService rolePermissionService;

    //用于缓存前端需要的状态码的缓存，Key为枚举名，Value为所有枚举值构造的map，如401-尚未登录
    public static Cache<String, Map<Integer, String>> ENUM_UTILS = CacheUtil.newLRUCache(100);
    //缓存当前工程目录下所有实现EnumInterface的子类（基本为枚举）,Key为枚举名，Value为所有枚举Class的名称（小写）
    public static Cache<String, Class<? extends EnumInterface>> CONFIG_UTIL;
    //缓存当前工程目录下所有实现AuthenticationInterface接口的子类，key为签发者ISS，value为具体实现
    public static Map<String, AuthenticationInterface> AUTHENTICATION;
    public static Map<PermissionCacheVO, Set<String>> adminPermissionRoleCache;
    public static Map<PermissionCacheVO, Set<String>> agentPermissionRoleCache;
    public static Map<PermissionCacheVO, Set<String>> companyPermissionRoleCache;

//------------------------------------------以上为基础架构所需缓存，请勿删除-------------------------------------------

    @Override
    public void run(ApplicationArguments applicationArguments) throws Exception {
        //初始化CONFIG_UTIL
        Reflections reflections = new Reflections(CommonConstant.PROJECT_PATH);
        Set<Class<? extends EnumInterface>> subTypesOf = reflections.getSubTypesOf(EnumInterface.class);
        CONFIG_UTIL = CacheUtil.newLRUCache(subTypesOf.size());
        for (Class<? extends EnumInterface> aClass : subTypesOf) {
            CONFIG_UTIL.put(aClass.getSimpleName().toLowerCase(), aClass);
        }
        //初始化AUTHENTICATION
        Map<String, AuthenticationInterface> authenticationInterfaceMap = SpringContextUtil.getBeanOfType(AuthenticationInterface.class);
        AUTHENTICATION = new HashMap<>();
        for (AuthenticationInterface authenticationInterface : authenticationInterfaceMap.values()) {
            AUTHENTICATION.put(authenticationInterface.getIss(), authenticationInterface);
        }
        //初始化adminPermissionRoleCache
        initAdminPermissionRoleCache();
        //初始化agentPermissionRoleCache
        initAgentPermissionRoleCache();
        //
        initCompanyPermissionRoleCache();
//------------------------------------------以上为基础架构所需缓存，请勿删除-------------------------------------------
    }

    public void initAdminPermissionRoleCache() {
        adminPermissionRoleCache = initCache(CommonConstant.ADMIN_ISSUER);
    }

    public void initAgentPermissionRoleCache() {
        agentPermissionRoleCache = initCache(CommonConstant.AGENT_ISSUER);
    }


    public void initCompanyPermissionRoleCache() {
        companyPermissionRoleCache = initCache(CommonConstant.COMPANY_ISSUER);
    }


    private Map<PermissionCacheVO, Set<String>> initCache(String iss) {
//        List<Permission> permissions = permissionMapper.findByLevel(3);
        List<Permission> permissions = permissionService.lambdaQuery()
                .eq(Permission::getLevel, 3)
                .eq(Permission::getType, iss)
                .list();
        //构造LRU缓存，大小为查找到的三级权限数
        Map<PermissionCacheVO, Set<String>> cache = new ConcurrentHashMap<>(permissions.size());
        //获取所有三级菜单的id
        Set<String> permissionIds = permissions.parallelStream().map(Permission::getId).collect(Collectors.toSet());
        //获取这些三级菜单的角色关系
//        List<RolePermission> rolePermissions = rolePermissionMapper.findByPermissionIdIn(permissionIds);
        List<RolePermission> rolePermissions = rolePermissionService.lambdaQuery()
                .in(!ParamUtil.isBlank(permissionIds), RolePermission::getPermissionId, permissionIds)
                .list();
        //构造权限Id-角色列表
        Map<String, Set<String>> permissionIdRoleMap = rolePermissions.parallelStream()
                .collect(Collectors.groupingBy(RolePermission::getPermissionId,
                        Collectors.mapping(RolePermission::getRoleId, Collectors.toSet())));
        for (Permission permission : permissions) {
            PermissionCacheVO vo = new PermissionCacheVO(permission.getId(), permission.getPath());
            Set<String> roleIds = permissionIdRoleMap.get(vo.getId());
            if (roleIds == null) {
                continue;
            }
            cache.put(vo, roleIds);
        }
        return cache;
    }

}
